#ifndef __UI_CONTROLS_H__
#define __UI_CONTROLS_H__

#include <set>

#include <QtCore>
#include <QtGui>
#include <QTableWidget>
#include <QLabel>
#include <QComboBox>
#include <QLineEdit>
#include <QProgressBar>
#include <QPushButton>
#include <QDialogButtonBox>
#include <QDialog>
#include <QVBoxLayout>
#include <QFileDialog>
#include <QHeaderView>
#include <QRadioButton>
#include <QSpinBox>
#include <QGroupBox>
#include <QItemDelegate>

#include <QGLViewer/qglviewer.h>

#include <mapwidget/opmapwidget.h>

#include <base/types/types.h>
#include <uav/UAS_types.h>
#include <uav/UAS.h>



////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class UI_diagAbout : public QDialog
{
    Q_OBJECT

public:
    explicit UI_diagAbout(QWidget *parent = 0, int autoClose=0);
    virtual ~UI_diagAbout();

    void setupUI(void);

public slots:
    void btnOK_clicked(bool checked);

    void mousePressEvent(QMouseEvent *ev);

protected:
    void timerEvent(QTimerEvent *event);

protected:
    QLabel                  *labLogo;
    QPushButton             *btnOK;

    int                     m_autoClose;
    double                  m_openTS;
};



////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class UI_diagUAVSelect : public QDialog
{
    Q_OBJECT

public:
    explicit UI_diagUAVSelect(QWidget *parent = 0, UAS_Manager *u = 0);
    virtual ~UI_diagUAVSelect();

    void setupUI(void);

    int setUASManager(UAS_Manager *u) { m_uasManager = u; }
    int getSelectedUAV(void);

protected:
    UAS_Manager         *m_uasManager;

    QLabel              *labUAV;
    QComboBox           *cbUAV;
    QDialogButtonBox    *buttonBox;
};


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class UI_paramterList : public QWidget
{
    Q_OBJECT

public:
    explicit UI_paramterList(QWidget *parent = 0);
    virtual ~UI_paramterList();

    int set_paramArray(AP_ParamArray *arrParam);
    int set_filter(QString sf);

    int resize_column_width(void);

protected:
    int set_paramArray_(QStringList &slID);
    int set_tableItem(int ri, AP_ParamItem *pi);
    int set_tableItem(int ri, int ci, QString s);



protected:
    QTableWidget        *m_tblParam;
    AP_ParamArray       *m_arrParam;
    QString             m_sFilter;

    QColor              clCL1, clCL2;
    QColor              clB1, clB2, clB3;
    int                 fontSize;
    int                 rowHeight;

    int                 m_updateCell;
    int                 m_tableFilled;

protected slots:
    void act_cellChanged(int row, int column);

protected:
    void resizeEvent(QResizeEvent * event);
};



////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class UI_AP_paramControl : public QWidget
{
    Q_OBJECT

public:
    explicit UI_AP_paramControl(QWidget *parent = 0);
    virtual ~UI_AP_paramControl();

    void setupUI(void);

    int set_UAS_Manager(UAS_Manager *uasManager);

protected:
    UAS_Manager         *m_uasManager;
    int                 m_activeUAS;

    UI_paramterList     *m_tblParam;

    QPushButton         *m_btnRead, *m_btnWrite;
    QPushButton         *m_btnLoad, *m_btnSave;
    QLineEdit           *m_edtFilter;
    QComboBox           *m_cbUAS;

protected:
    virtual void timerEvent(QTimerEvent *event);

public slots:
    void cbUAS_currentIndexChanged(const QString &text);

    void btnRead_clicked(bool checked=false);
    void btnWrite_clicked(bool checked=false);
    void btnSave_clicked(bool checked=false);
    void btnLoad_clicked(bool checked=false);

    void edtFilter_editingFinished(void);
};


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class UI_waypointDelegate : public QItemDelegate
{
    Q_OBJECT

public:
    UI_waypointDelegate(QObject *parent = 0);

    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
                          const QModelIndex &index) const;

    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model,
                      const QModelIndex &index) const;

    void updateEditorGeometry(QWidget *editor,
                              const QStyleOptionViewItem &option, const QModelIndex &index) const;

protected:
    QStringList     m_wpTypeList;
};


class UI_waypointEdit : public QWidget
{
    Q_OBJECT

public:
    explicit UI_waypointEdit(QWidget *parent = 0);
    virtual ~UI_waypointEdit();

    void setupUi(void);


    int setWaypoints(int idx,
                     QMap<int, mapcontrol::WayPointItem*> *wpMap,
                     int heightAltitude = 1);
    int setWaypoints_(int idx,
                      QMap<int, mapcontrol::WayPointItem*> *wpMap,
                      int heightAltitude);

    int setTableItem(int ri, int ci, QString s);
    int updateWaypoints(void);

    void setReferenceAltitude(double alt);
    double getReferenceAltitude(void);

    void initWaypointList(void);

protected slots:
    void act_cbAllWaypoints_clicked(bool s);
    void act_cbHeightAltitude_clicked(bool s);

    void act_btnSetAllHeight(void);

private:
    QVBoxLayout         *verticalLayout;

    QTableView          *wpTable;                           ///< table view
    QStandardItemModel  *wpModel;                           ///< table model
    UI_waypointDelegate *wpDelegate;                        ///< item widget delegate

    QTableWidget        *tableWaypoints;                    ///< waypoint table


    QCheckBox           *cbAllWaypoints;                    ///< checkbox for all waypoints
    QCheckBox           *cbHeightAltitude;                  ///< checkbox for height/altitude

    QMap<int, mapcontrol::WayPointItem*>    *m_wpMap;       // waypoints map
    int                                     m_wpIdx;        // active waypoint index

    int                 m_bHeightAltitude;                  // height or altitude
    double              m_homeAltitude;                     // home altitude (reference)

    QColor              clCL1, clCL2;
    QColor              clB1, clB2;
    int                 fontSize;
    int                 rowHeight;
};


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class UI_diagMissionProgress : public QDialog
{
    Q_OBJECT

public:
    explicit UI_diagMissionProgress(QWidget *parent = 0);
    virtual ~UI_diagMissionProgress();

    void setupUI(void);

    int setUAS(UAS_Base *u, int t=0);

protected:
    UAS_Base            *m_uas;

    QLabel              *m_labStatus;
    QProgressBar        *m_progressBar;
    QDialogButtonBox    *m_buttonBox;

    int                 m_iReadWriteType;       ///< dialog type (0 - read, 1 - write)
    int                 m_bFinished;

protected:
    virtual void timerEvent(QTimerEvent *event);
};



////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class UI_diagParamProgress : public QDialog
{
    Q_OBJECT

public:
    explicit UI_diagParamProgress(QWidget *parent = 0);
    virtual ~UI_diagParamProgress();

    void setupUI(void);

    int setUAS(UAS_Base *u, int rw=0);


protected:
    UAS_Base            *m_uas;
    int                 m_rw;                       ///< 0 - reading, 1 - writting

    QLabel              *m_labStatus;
    QProgressBar        *m_progressBar;

    int                 m_bFinished;

protected:
    virtual void timerEvent(QTimerEvent *event);
};



////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class UI_diagComOpen : public QDialog
{
    Q_OBJECT

public:
    enum ComDev_Type {
        COMDEV_UART,
        COMDEV_FILE,
        COMDEV_VIRTUAL_UAV,
        COMDEV_UDP
    };

public:
    explicit UI_diagComOpen(QWidget *parent = 0);
    virtual ~UI_diagComOpen();

    void setupUI(void);

    int getDevInfo(ComDev_Type &t, QString &v1, QString &v2);


public slots:
    void rbUART_clicked(bool checked);
    void cbUART_port_currentIndexChanged(const QString &text);
    void cbUART_baud_currentIndexChanged(const QString &text);

    void rbFILE_clicked(bool checked);
    void btnOpen_clicked(bool checked);

    void rbVUAV_clicked(bool checked);
    void cbVUAV_type_currentIndexChanged(const QString &text);
    void cbVUAV_ID_currentIndexChanged(const QString &text);

    void rbUDP_clicked(bool checked);
    void sbUPD_port_valueChanged(int i);

protected:
    QDialogButtonBox        *buttonBox;

    QLabel                  *labDevice;

    QRadioButton            *rbUART;
    QComboBox               *cbUART_port;
    QComboBox               *cbUART_baud;

    QRadioButton            *rbFile;
    QPushButton             *btnOpen;

    QRadioButton            *rbVUAV;
    QComboBox               *cbVUAV_type;
    QComboBox               *cbVUAV_ID;

    QRadioButton            *rbUDP;
    QSpinBox                *sbUDP_port;

    QLabel                  *labDevInfo;
    QLineEdit               *edtDevInfo;

    QString                 m_fileName;
};



////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class UI_rcValueBar : public QProgressBar
{
    Q_OBJECT

public:
    explicit UI_rcValueBar(QWidget *parent = 0);
    virtual ~UI_rcValueBar();

    void setValue(int value);

    void setMinMaxVal(int vMin, int vMax);

protected:
    void paintEvent(QPaintEvent *event);

protected:
    int     m_vMin, m_vMax;
};


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class UI_rcViewWidget : public QWidget
{
    Q_OBJECT

public:
    explicit UI_rcViewWidget(QWidget *parent = 0);
    virtual ~UI_rcViewWidget();

    void setupUi(void);

    void setRCChannel(int c);
    void setRCVal(int v);

    void setDZ(int  rcDZ) { m_rcDZ = rcDZ; leDZ->setText(QString("%1").arg(m_rcDZ)); }
    void getDZ(int &rcDZ) { rcDZ = m_rcDZ; }
    void setTrim(int  rcTrim) { m_rcTrim = rcTrim; leTrim->setText(QString("%1").arg(m_rcTrim)); }
    void getTrim(int &rcTrim) { rcTrim = m_rcTrim; }
    void setTrimMode(int  trimMode) { m_trimMode = trimMode; }
    void getTrimMode(int &trimMode) { trimMode = m_trimMode; }

    void setSettings(int  rcMin, int  rcMax, int  rcDZ, int  rcTrim);
    void getSettings(int &rcMin, int &rcMax, int &rcDZ, int &rcTrim);

public:
    static const int    m_widgetW = 502,
                        m_widgetH = 72;

protected:
    int                 m_rcChannel;
    int                 m_rcMin, m_rcMax, m_rcVal;      ///< RC values, min/max
    int                 m_rcDZ, m_rcTrim;               ///< RC deadzone and trim
    int                 m_trimMode;                     ///< 0 - min, 1 - middle, 2 - max

private:
    QGroupBox           *rcGroup;
    QLabel              *labDZ;
    QLabel              *labTrim;
    UI_rcValueBar       *pbRCValue;
    QLineEdit           *leTrim;
    QLineEdit           *leInfo;
    QLineEdit           *leDZ;
};


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class UI_rcConfigControl : public QWidget
{
    Q_OBJECT

public:
    explicit UI_rcConfigControl(QWidget *parent = 0);
    virtual ~UI_rcConfigControl();

    void setupUI(void);

    int setUAS(UAS_Base *uas);
    int parseMavlinkMsg(mavlink_message_t *msg);

    void _close(void);


protected:
    UAS_Base            *m_uas;

    QVector<UI_rcViewWidget*>   rcViewers;


    QPushButton         *pbBegin;
    QPushButton         *pbEnd;
    QPushButton         *pbWrite;
    QPushButton         *pbClose;

    int                 m_isCalibration;
    int                 m_oldRCRawFreq;

    int                 m_rcRaw[8];

protected:
    virtual void timerEvent(QTimerEvent *event);
    virtual void closeEvent(QCloseEvent *event);


public slots:
    void btnBegin_clicked(bool checked=false);
    void btnEnd_clicked(bool checked=false);
    void btnWrite_clicked(bool checked=false);
    void btnClose_clicked(bool checked=false);
};



////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class UI_flightModeWidget : public QWidget
{
    Q_OBJECT

public:
    explicit UI_flightModeWidget(QWidget *parent = 0);
    virtual ~UI_flightModeWidget();

    void setupUi(void);

    void setModeIndex(int c);
    void setActive(int active=1);

    void setFlightMode(int fm);
    int  getFlightMode(void);


public:
    static const int    m_widgetW = 335,
                        m_widgetH = 40;

protected:
    int                 m_modeIndex;
    int                 m_isActive;

private:
    QLabel              *labModeIndex;
    QComboBox           *cbFlightType;

    QStringList                 m_flightModeStrings;
    std::map<std::string, int>  m_flightModeMap;
};


class UI_flightModeConfig : public QWidget
{
    Q_OBJECT

public:
    explicit UI_flightModeConfig(QWidget *parent = 0);
    virtual ~UI_flightModeConfig();

    void setupUI(void);

    int setUAS(UAS_Base *uas);
    int parseMavlinkMsg(mavlink_message_t *msg);
    int release(void);


public slots:
    void btnClose_clicked(bool checked);
    void btnWrite_clicked(bool checked);

    virtual void timerEvent(QTimerEvent *event);
    virtual void closeEvent(QCloseEvent *event);

protected:
    UAS_Base                *m_uas;
    int                     m_flightModeChannel;
    int                     m_rcRaw[8];
    int                     m_oldRCRawFreq;

    static const int        m_flightModes = 6;
    UI_flightModeWidget     *m_fmControls[m_flightModes];

    QPushButton             *btnWrite;
    QPushButton             *btnClose;
};



////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class UI_diagAccelConfig : public QWidget
{
    Q_OBJECT

public:
    explicit UI_diagAccelConfig(QWidget *parent = 0);
    virtual ~UI_diagAccelConfig();

    void setupUI(void);

    int setUAS(UAS_Base *uas);
    int parseMavlinkMsg(mavlink_message_t *msg);
    int release(void);


public slots:
    void btnBegin_clicked(bool checked);
    void btnNext_clicked(bool checked);
    void btnClose_clicked(bool checked);

    virtual void closeEvent(QCloseEvent *event);

protected:
    UAS_Base                *m_uas;

    int                     msgSeverity;
    char                    msgText[256];

    int                     m_accelAckCount;

    QLabel                  *labMsg;
    QLineEdit               *leMsg;

    QPushButton             *btnBegin;
    QPushButton             *btnNext;
    QPushButton             *btnClose;
};


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class UI_compassViewer : public QGLViewer
{
    Q_OBJECT

public :
    UI_compassViewer(QWidget *parent);

    int addData(pi::Point3d &dat);
    int clearData(void);

protected:
    virtual void draw(void);
    virtual QString helpString() const;
    virtual void timerEvent(QTimerEvent *event);
    virtual void keyPressEvent(QKeyEvent *e);


protected:
    std::vector<pi::Point3d>    m_data;
    double                      m_maxLeng;

    double                      m_viewDis;
    double                      m_viewPitch, m_viewYaw;

    pi::Mutex                   m_mutex;
};


////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class UI_compassConfigControl : public QWidget
{
    Q_OBJECT

public:
    explicit UI_compassConfigControl(QWidget *parent = 0);
    virtual ~UI_compassConfigControl();

    void setupUI(void);

    int setUAS(UAS_Base *uas);
    int parseMavlinkMsg(mavlink_message_t *msg);

    void _begin(void);
    void _end(void);
    void _cancel(void);
    void _write(void);
    void _close(void);

protected:
    UAS_Base                    *m_uas;

    QGroupBox                   *gpCompass1;
    QLabel                      *labOri1;
    QComboBox                   *cbOri1;
    QLabel                      *labOff1;
    QLineEdit                   *leOri1;

    QGroupBox                   *gpCompass2;
    QLabel                      *labOri2;
    QComboBox                   *cbOri2;
    QLabel                      *labOff2;
    QLineEdit                   *leOri2;

    QPushButton                 *pbBegin;
    QPushButton                 *pbEnd;
    QPushButton                 *pbCancel;
    QPushButton                 *pbWrite;
    QPushButton                 *pbClose;

    UI_compassViewer            *viewer1;
    UI_compassViewer            *viewer2;


    int                         m_isCalibration;
    pi::Point3d                 m_off1, m_off2;
    pi::Point3d                 m_offNew1, m_offNew2;

    int                         m_devID1, m_devID2;

    int                         old_streamRawSensorsFreq;
    std::vector<pi::Point3d>    m_compass1Data;
    std::vector<pi::Point3d>    m_compass2Data;

protected:
    virtual void timerEvent(QTimerEvent *event);
    virtual void closeEvent(QCloseEvent *event);

public slots:
    void btnBegin_clicked(bool checked=false);
    void btnEnd_clicked(bool checked=false);
    void btnCancel_clicked(bool checked=false);
    void btnWrite_clicked(bool checked=false);
    void btnClose_clicked(bool checked=false);
};



////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

class UI_flightControlPanel : public QWidget
{
    Q_OBJECT

public:
    explicit UI_flightControlPanel(QWidget *parent = 0);
    virtual ~UI_flightControlPanel();

    void setupUI(void);

    int setUASManager(UAS_Manager *uasManager);
    int parseMavlinkMsg(mavlink_message_t *msg);

    int updateUAVs(void);
    int changeActiveUAV(int oldUAV, int newUAV, int confirm);

protected:
    UAS_Manager         *m_uasManager;

    int                 m_currUAV, m_oldUAV;
    std::set<int>       m_uavList;

    enum Command {
        CMD_NONE                = 0,
        CMD_CH_FLIGHTMODE,
        CMD_ARM,
        CMD_DISARM,
        CMD_TAKEOFF,
        CMD_LAND,
        CMD_RTL,
        CMD_STARTMISSION,
        CMD_CHANGESPEED,
    };
    Command             m_lastCMD;
    double              m_tmLastCmd;

    // controls
    QLabel              *labUAS;
    QComboBox           *cbUAS;
    QLabel              *labFlightMode;
    QComboBox           *cbFlightMode;
    QLineEdit           *edStatus;

    QPushButton         *btnArmDisarm;
    QPushButton         *btnTakeoff;
    QPushButton         *btnLand;
    QPushButton         *btnRTL;


    QPushButton         *btnAutoFlight;
    QPushButton         *btnStartMission;
    QPushButton         *btnChangeSpeed;
    QPushButton         *btnUploadMission;
    QPushButton         *btnDownloadMission;
    QPushButton         *btnLandingGearDown;
    QPushButton         *btnLandingGearUp;

    QPushButton         *btnFollowMeStart;
    QPushButton         *btnFollowMeStop;

protected:
    virtual void timerEvent(QTimerEvent *event);

public slots:
    void btnArmDisarm_clicked(bool checked=false);
    void btnTakeoff_clicked(bool checked=false);
    void btnLand_clicked(bool checked=false);
    void btnRTL_clicked(bool checked=false);

    void btnAutoFlight_clicked(bool checked=false);
    void btnStartMission_clicked(bool checked=false);
    void btnChangeSpeed_clicked(bool checked=false);
    void btnUploadMission_clicked(bool checked=false);
    void btnDownloadMission_clicked(bool checked=false);
    void btnLandingGearDown_clicked(bool checked=false);
    void btnLandingGearUp_clicked(bool checked=false);

    void btnFollowMeStart_clicked(bool checked=false);
    void btnFollowMeStop_clicked(bool checked=false);

    void cbFlightMode_currentIndexChanged(int index);
    void cbUAS_currentIndexChanged(int index);
};

#endif // end of __UI_CONTROLS_H__
